/**
************************************************************
* @file         gizwits_product.c
* @brief        Gizwits control protocol processing, and platform-related       hardware initialization 
* @author       Gizwits
* @date         2017-07-19
* @version      V03030000
* @copyright    Gizwits
* 
* @note         机智云.只为智能硬件而生
*               Gizwits Smart Cloud  for Smart Products
*               链接|增值ֵ|开放|中立|安全|自有|自由|生态
*               www.gizwits.com
*
***********************************************************/

#include <stdio.h>
#include <string.h>
#include <at32f4xx.h>
#include "at32f4xx_usart.h"
#include "drv_usart.h"
#include "drv_gpio.h"
//#include "hal_key.h"
#include "gizwits_product.h"
#include "common.h"
#include <rtthread.h>

#define USER_KEY    GET_PIN(A, 0)

extern rt_device_t serial;
static uint32_t timerMsCount;
uint8_t aRxBuffer;
static rt_timer_t timer_ms;

uint8_t delay = 0;
/** User area the current device state structure*/
dataPoint_t currentDataPoint;
dataPoint_t *dataPointPtr;

/**@} */
/**@name Gizwits User Interface
* @{
*/

/**
* @brief Event handling interface

* Description:

* 1. Users can customize the changes in WiFi module status

* 2. Users can add data points in the function of event processing logic, such as calling the relevant hardware peripherals operating interface

* @param [in] info: event queue
* @param [in] data: protocol data
* @param [in] len: protocol data length
* @return NULL
* @ref gizwits_protocol.h
*/
int8_t gizwitsEventProcess(eventInfo_t *info, uint8_t *gizdata, uint32_t len)
{
  uint8_t i = 0;
  dataPointPtr = (dataPoint_t *)gizdata;
  moduleStatusInfo_t *wifiData = (moduleStatusInfo_t *)gizdata;
  protocolTime_t *ptime = (protocolTime_t *)gizdata;
  
#if MODULE_TYPE
  gprsInfo_t *gprsInfoData = (gprsInfo_t *)gizdata;
#else
  moduleInfo_t *ptModuleInfo = (moduleInfo_t *)gizdata;
#endif

  if((NULL == info) || (NULL == gizdata))
  {
    return -1;
  }

  for(i=0; i<info->num; i++)
  {
    switch(info->event[i])
    {
      case EVENT_ventilate:
        currentDataPoint.valueventilate = dataPointPtr->valueventilate;
        GIZWITS_LOG("Evt: EVENT_ventilate %d \n", currentDataPoint.valueventilate);
        if(0x01 == currentDataPoint.valueventilate)
        {
            rt_pin_write(GET_PIN(B, 8), PIN_LOW);//通风
        }
        else
        {
            rt_pin_write(GET_PIN(B, 8), PIN_HIGH);//user handle    
        }
        break;
      case EVENT_warm:
        currentDataPoint.valuewarm = dataPointPtr->valuewarm;
        GIZWITS_LOG("Evt: EVENT_warm %d \n", currentDataPoint.valuewarm);
        if(0x01 == currentDataPoint.valuewarm)
        {
            
					  rt_pin_write(20, PIN_LOW);            //电机
				  	rt_pin_write(21, PIN_HIGH);
				
        }
        else
        {
					  rt_pin_write(20, PIN_LOW);
				  	rt_pin_write(21, PIN_LOW);
					
        }
        break;
      case EVENT_Inside:
        currentDataPoint.valueInside = dataPointPtr->valueInside;
        GIZWITS_LOG("Evt: EVENT_Inside %d \n", currentDataPoint.valueInside);
        if(0x01 == currentDataPoint.valueInside)
        {
             rt_pin_write(GET_PIN(B, 9), PIN_LOW);//灌溉
        }
        else
        {
             rt_pin_write(GET_PIN(B, 9), PIN_HIGH);//
        }
        break;
      case EVENT_light:
        currentDataPoint.valuelight = dataPointPtr->valuelight;
        GIZWITS_LOG("Evt: EVENT_light %d \n", currentDataPoint.valuelight);
        if(0x01 == currentDataPoint.valuelight)
        {
             rt_pin_write(GET_PIN(D, 2), PIN_LOW);//光照补充
        }
        else
        {
             rt_pin_write(GET_PIN(D, 2), PIN_HIGH);//光照补充 
        }
        break;


      case EVENT_temp:
        currentDataPoint.valuetemp = dataPointPtr->valuetemp;
        GIZWITS_LOG("Evt:EVENT_temp %d\n",currentDataPoint.valuetemp);
        //user handle
        break;
      case EVENT_humid:
        currentDataPoint.valuehumid = dataPointPtr->valuehumid;
        GIZWITS_LOG("Evt:EVENT_humid %d\n",currentDataPoint.valuehumid);
        //user handle
        break;
      case EVENT_data1:
        currentDataPoint.valuedata1 = dataPointPtr->valuedata1;
        GIZWITS_LOG("Evt:EVENT_data1 %d\n",currentDataPoint.valuedata1);
        //user handle
        break;
      case EVENT_data2:
        currentDataPoint.valuedata2 = dataPointPtr->valuedata2;
        GIZWITS_LOG("Evt:EVENT_data2 %d\n",currentDataPoint.valuedata2);
        //user handle
        break;


      case WIFI_SOFTAP:
        break;
      case WIFI_AIRLINK:
        break;
      case WIFI_STATION:
        break;
      case WIFI_CON_ROUTER:
 
        break;
      case WIFI_DISCON_ROUTER:
 
        break;
      case WIFI_CON_M2M:
 
        break;
      case WIFI_DISCON_M2M:
        break;
      case WIFI_RSSI:
        GIZWITS_LOG("RSSI %d\n", wifiData->rssi);
        break;
      case TRANSPARENT_DATA:
        GIZWITS_LOG("TRANSPARENT_DATA \n");
        //user handle , Fetch data from [data] , size is [len]
        break;
      case WIFI_NTP:
        GIZWITS_LOG("WIFI_NTP : [%d-%d-%d %02d:%02d:%02d][%d] \n",ptime->year,ptime->month,ptime->day,ptime->hour,ptime->minute,ptime->second,ptime->ntp);
        break;
      case MODULE_INFO:
            GIZWITS_LOG("MODULE INFO ...\n");
      #if MODULE_TYPE
            GIZWITS_LOG("GPRS MODULE ...\n");
            //Format By gprsInfo_t
      #else
            GIZWITS_LOG("WIF MODULE ...\n");
            //Format By moduleInfo_t
            GIZWITS_LOG("moduleType : [%d] \n",ptModuleInfo->moduleType);
      #endif
    break;
      default:
        break;
    }
  }

  return 0;
}

/**
* User data acquisition

* Here users need to achieve in addition to data points other than the collection of data collection, can be self-defined acquisition frequency and design data filtering algorithm

* @param none
* @return none
*/
void userHandle(void)
{
 /*

    */
    
}

/**
* Data point initialization function

* In the function to complete the initial user-related data
* @param none
* @return none
* @note The developer can add a data point state initialization value within this function
*/
void userInit(void)
{
    memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));
    
    /** Warning !!! DataPoint Variables Init , Must Within The Data Range **/ 
    /*
      currentDataPoint.valueventilate = ;
      currentDataPoint.valuewarm = ;
      currentDataPoint.valueInside = ;
      currentDataPoint.valuelight = ;
      currentDataPoint.valuetemp = ;
      currentDataPoint.valuehumid = ;
      currentDataPoint.valuedata1 = ;
      currentDataPoint.valuedata2 = ;
    */

}


/**
* @brief Millisecond timing maintenance function, milliseconds increment, overflow to zero

* @param none
* @return none
*/
static void gizTimerMs(void *parameter)
{
    timerMsCount++;
	  if(rt_pin_read(USER_KEY) == 1)
		{   
			  if(delay == 1)
				{				
       			delay = 0;		
				    gizwitsSetMode(0x02);
				}
				else
				{
				    delay = 1;
				}
		}
}

/**
* @brief Read millisecond count

* @param none
* @return millisecond count
*/
uint32_t gizGetTimerCount(void)
{
    return timerMsCount;
}

/**
* @brief MCU reset function

* @param none
* @return none
*/
void mcuRestart(void)
{
    __set_FAULTMASK(1);
    NVIC_SystemReset();
}

/**@} */

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
//PUTCHAR_PROTOTYPE
//{
//  /* Place your implementation of fputc here */
//  /* e.g. write a character to the USART1 and Loop until the end of transmission */
//  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
// 
//  return ch;
//}

/**
  * @brief  Period elapsed callback in non blocking mode 
  * @param  htim : TIM handle
  * @retval None
  */
//void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
//{
//	if(htim==&htim2)
//	{
//			keyHandle((keysTypedef_t *)&keys);
//			gizTimerMs();
//	}
//}

/**
* @brief Timer TIM3 init function

* @param none
* @return none
*/
//void timerInit(void)
//{
//	HAL_TIM_Base_Start_IT(&htim2);
//}

/**
  * @brief  This function handles USART IDLE interrupt.
  */
//void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)  
//{  
//    if(UartHandle->Instance == USART2)  
//    {  
//				gizPutData((uint8_t *)&aRxBuffer, 1);

//        HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断  
//    }  
//}  

/**
* @brief USART init function

* Serial communication between WiFi modules and device MCU
* @param none
* @return none
*/
//void uartInit(void)
//{
//	HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断  
//}

/**
* @brief Serial port write operation, send data to WiFi module
*
* @param buf      : buf address
* @param len      : buf length
*
* @return : Return effective data length;-1，return failure
*/
int32_t uartWrite(uint8_t *buf, uint32_t len)
{
		uint8_t crc[1] = {0x55};
    uint32_t i = 0;
	
    if(NULL == buf)
    {
        return -1;
    }

    for(i=0; i<len; i++)
    {
			  rt_device_write(serial, 0, (uint8_t *)&buf[i], 1);
				//while (USART_GetITStatus(USART2, USART_INT_TRAC) != SET);//Loop until the end of transmission
        
        if(i >=2 && buf[i] == 0xFF)
        {
					  rt_device_write(serial, 0, (uint8_t *)&crc, 1);
						//while (USART_GetITStatus(USART2, USART_INT_TRAC)!= SET);//Loop until the end of transmission
        }
    }

#ifdef PROTOCOL_DEBUG
    GIZWITS_LOG("MCU2WiFi[%4d:%4d]: ", gizGetTimerCount(), len);
    for(i=0; i<len; i++)
    {
        GIZWITS_LOG("%02x ", buf[i]);

        if(i >=2 && buf[i] == 0xFF)
        {
            GIZWITS_LOG("%02x ", 0x55);
        }
    }
    GIZWITS_LOG("\n");
#endif
		
		return len;
}  

void timer_init(void)
{
    /* 创建定时器 1  周期定时器 */
    timer_ms = rt_timer_create("timer_ms", gizTimerMs,
                             RT_NULL, 10,
                             RT_TIMER_FLAG_PERIODIC);

  	/* 启动定时器 1 */
	  if(timer_ms != RT_NULL) rt_timer_start(timer_ms);
}

INIT_APP_EXPORT(timer_init);


